package com.zhongwang.mms.module.material.service;

import com.zhongwang.mms.gen.entity.BReportPlan;
import com.zhongwang.mms.gen.entity.MChangeOrder;
import com.zhongwang.mms.gen.entity.MChangeOrderExample;
import com.zhongwang.mms.gen.entity.MInventory;
import com.zhongwang.mms.gen.mapper.BReportPlanMapper;
import com.zhongwang.mms.module.material.dao.MChangeOrderDao;
import com.zhongwang.mms.module.material.dao.MInventoryDao;
import com.zhongwang.mms.module.material.dao.MOrderDetailDao;
import com.zhongwang.mms.module.material.model.MChangeOrderModel;
import com.zhongwang.mms.module.material.model.MProCodeQueryModel;
import com.zhongwang.mms.module.overview.model.ProjectStatusModel;
import com.zhongwang.mms.module.system.log.LogService;
import com.zhongwang.mms.util.ShiroUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @Description: 串料申请 服务层
 * @Author: China.wsg
 * @Date: 2020/04/13 16:49
 */
@Service
public class MChangeOrderService {

    @Autowired
    private MChangeOrderDao changeOrderDao;
    @Autowired
    private LogService logService;
    @Autowired
    private MInventoryDao inventoryDao;
    @Autowired
    private MInventoryService inventoryService;
    @Autowired
    private BReportPlanMapper reportPlanMapper;
    @Autowired
    private MOrderDetailDao orderDetailDao;


    /**
     * 保存串料申请单
     *
     * @param changeOrder 保存信息
     * @return
     */
    public int saveChangeOrder(MChangeOrder changeOrder) {

        // 取得当日零时时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date date = calendar.getTime();

        String orderCode; // 串料申请单号：MCL+年月日+3位流水号 MRK200317001
        MChangeOrderExample ex = new MChangeOrderExample();
        ex.setOrderByClause("ceo_id desc");
        MChangeOrderExample.Criteria criteria = ex.createCriteria();
        criteria.andCeoBillDateGreaterThan(date);
        List<MChangeOrder> changeOrders = changeOrderDao.selectByExample(ex);
        // 获取单据编号
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        if (changeOrders != null && changeOrders.size() > 0) {
            orderCode = "MCL" + dateFormat.format(new Date()).substring(2) + String.format("%0" + 3 + "d", Integer.parseInt(changeOrders.get(0).getCeoCode().substring(9, 12)) + 1);
        } else {
            orderCode = "MCL" + dateFormat.format(new Date()).substring(2) + "001";
        }

        changeOrder.setCeoCode(orderCode);
        changeOrder.setCeoBillUser(ShiroUtils.getUser().getName());
        changeOrder.setCeoStatus(1);
        changeOrder.setCeoUserName(ShiroUtils.getLoginName());
        changeOrder.setCeoBillDate(new Date());
        changeOrder.setCeoNeedCode(changeOrder.getCeoNeedCode().toUpperCase()); // 小写转大写

        logService.saveLog("创建串料申请单", "单据编号：" + orderCode);
        int row = changeOrderDao.insert(changeOrder);
        return row;
    }

    /**
     * 串料申请列表
     *
     * @param changeOrderModel 查询条件
     * @return 原料基础列表
     */
    public List<MChangeOrder> findMChangeOrderByQuery(MChangeOrderModel changeOrderModel) {

        MChangeOrderExample ex = new MChangeOrderExample();
        ex.setOrderByClause("ceo_status asc,ceo_id desc");
        MChangeOrderExample.Criteria criteria = ex.createCriteria();
        criteria.andCeoStatusNotEqualTo(0);
        if (changeOrderModel.getCeoNeedCode() != null && !"".equals(changeOrderModel.getCeoNeedCode())) {
            criteria.andCeoNeedCodeLike("%" + changeOrderModel.getCeoNeedCode() + "%");
        }
        if (changeOrderModel.getCeoNeedName() != null && !"".equals(changeOrderModel.getCeoNeedName())) {
            criteria.andCeoNeedNameLike("%" + changeOrderModel.getCeoNeedName() + "%");
        }
        if (changeOrderModel.getCeoLendCode() != null && !"".equals(changeOrderModel.getCeoLendCode())) {
            criteria.andCeoLendCodeLike("%" + changeOrderModel.getCeoLendCode() + "%");
        }
        if (changeOrderModel.getCeoLendName() != null && !"".equals(changeOrderModel.getCeoLendName())) {
            criteria.andCeoLendNameLike("%" + changeOrderModel.getCeoLendName() + "%");
        }
        if (changeOrderModel.getCeoNeedDept() != null && !"".equals(changeOrderModel.getCeoNeedDept())) {
            criteria.andCeoNeedDeptLike("%" + changeOrderModel.getCeoNeedDept() + "%");
        }
        if (changeOrderModel.getCeoStatus() != null && !"".equals(changeOrderModel.getCeoStatus())) {
            criteria.andCeoStatusEqualTo(changeOrderModel.getCeoStatus());
        }
        if (changeOrderModel.getCeoCode() != null && !"".equals(changeOrderModel.getCeoCode())) {
            criteria.andCeoCodeLike("%" + changeOrderModel.getCeoCode() + "%");
        }
        if (changeOrderModel.getCeoBillUser() != null && !"".equals(changeOrderModel.getCeoBillUser())) {
            criteria.andCeoBillUserLike("%" + changeOrderModel.getCeoBillUser() + "%");
        }
        if (changeOrderModel.getStartTimeQuery() != null && !"".equals(changeOrderModel.getStartTimeQuery())) {
            criteria.andCeoBillDateGreaterThanOrEqualTo(changeOrderModel.getStartTimeQuery());
        }
        if (changeOrderModel.getEndTimeQuery() != null && !"".equals(changeOrderModel.getEndTimeQuery())) {
            criteria.andCeoBillDateLessThanOrEqualTo(changeOrderModel.getEndTimeQuery());
        }
        if (changeOrderModel.getCeoCheckStatusListQuery() != null && changeOrderModel.getCeoCheckStatusListQuery().size() > 0) {
            criteria.andCeoStatusIn(changeOrderModel.getCeoCheckStatusListQuery());
        }

        return changeOrderDao.selectByExample(ex);
    }

    /**
     * 修改串料申请状态
     *
     * @param changeOrder 修改信息
     * @return
     */
    @Transactional
    public int updateStatus(MChangeOrder changeOrder) {

        String statusName = "";
        if (changeOrder.getCeoStatus() == 0) {
            statusName = "删除串料申请单";
        } else if (changeOrder.getCeoStatus() == 2) {
            statusName = "提交串料申请单";
        } else if (changeOrder.getCeoStatus() == 7) {
            statusName = "驳回串料申请单";
        }

        logService.saveLog(statusName, "单据编号：" + changeOrderDao.selectByPrimaryKey(changeOrder.getCeoId()).getCeoCode());
        int row = changeOrderDao.updateByPrimaryKeySelective(changeOrder);
        return row;
    }

    /**
     * 修改串料申请单
     *
     * @param changeOrder 保存信息
     * @return
     */
    @Transactional
    public int editChangeOrder(MChangeOrder changeOrder) {

        MChangeOrder mChangeOrder = changeOrderDao.selectByPrimaryKey(changeOrder.getCeoId());
        changeOrder.setCeoStatus(1);
        changeOrder.setCeoCode(mChangeOrder.getCeoCode());
        changeOrder.setCeoBillUser(mChangeOrder.getCeoBillUser());
        changeOrder.setCeoBillDate(mChangeOrder.getCeoBillDate());
        changeOrder.setCeoUserName(mChangeOrder.getCeoUserName());
        changeOrder.setCeoNeedCode(changeOrder.getCeoNeedCode().toUpperCase());    // 小写转大写

        logService.saveLog("修改串料申请单<br>单据编号：" + mChangeOrder.getCeoCode(), mChangeOrder, changeOrder);
        int row = changeOrderDao.updateByPrimaryKey(changeOrder);
        return row;
    }

    /**
     * 串料申请执行（单条执行）
     *
     * @param ceoId 申请Id
     * @return
     */
    @Transactional
    public String checkSingle(Integer ceoId) {

        String msg = "";  // 返回提示信息
        String errorReason;

        // 取得单据及库存
        MChangeOrder changeOrder = changeOrderDao.selectByPrimaryKey(ceoId);
        MInventory inventory = inventoryDao.selectByPrimaryKey(changeOrder.getCeoLendItyId());

        // 校验是否满足执行（审核）条件
        errorReason = checkValidate(changeOrder, inventory);
        if (errorReason.length() == 0) {

            // 满足执行条件 执行审核操作
            checkChangeOrderMethod(changeOrder, inventory);
        } else {
            msg = msg + errorReason + "  ，执行失败！";
            return msg;
        }

        logService.saveLog("串料申请执行", "单据编号：" + changeOrder.getCeoCode() + "<br> 原料描述：" + changeOrder.getCeoNeedMatDesc()
                + "<br> 跟踪号：" + changeOrder.getCeoNeedTrackCode() + "<br> 项目信息" + changeOrder.getCeoNeedCode() + "  " + changeOrder.getCeoNeedDesc()
                + "<br> 重量：" + changeOrder.getCeoNeedWgt());
        return "执行成功！";
    }

    /**
     * 串料申请执行（批量执行）
     *
     * @param arr 申请Id集合
     * @return
     */
    @Transactional
    public String checkTogether(List<Integer> arr) {

        String msg = "";  // 返回提示信息
        String errorReason; // 红冲校验原因
        int errorCount = 0; // 审核失败记录数
        int successCount = 0; // 成功审核记录数
        MChangeOrder changeOrder;
        MInventory inventory;

        for (int i = 0; i < arr.size(); i++) {

            // 取得单据及库存
            changeOrder = changeOrderDao.selectByPrimaryKey(arr.get(i));
            inventory = inventoryDao.selectByPrimaryKey(changeOrder.getCeoLendItyId());

            // 校验是否满足执行（审核）条件
            errorReason = checkValidate(changeOrder, inventory);
            if (errorReason.length() == 0) {

                // 满足执行条件 执行审核操作
                checkChangeOrderMethod(changeOrder, inventory);
                successCount++;
            } else {
                msg = msg + errorReason;
                errorCount++;
                continue;
            }
        }

        logService.saveLog("串料申请单批量执行", "执行成功：" + successCount + "条, 执行失败：" + errorCount + "条");
        return msg.length() > 0 ? msg + "<br> 以上数据执行失败！" : "执行成功！";
    }

    /**
     * 撤销被执行串料（单条）
     *
     * @param ceoId 申请Id
     * @return
     */
    @Transactional
    public String cancelSingle(Integer ceoId) {

        String msg = "";  // 返回提示信息
        String errorReason;

        // 取得单据及库存
        MChangeOrder changeOrder = changeOrderDao.selectByPrimaryKey(ceoId);
        MInventory lendInventory = inventoryDao.selectByPrimaryKey(changeOrder.getCeoLendItyId());
        MInventory needInventory = inventoryDao.selectByPrimaryKey(changeOrder.getCeoNeedItyId());

        // 校验是否满足撤销条件
        errorReason = checkCancelValidate(changeOrder, needInventory);
        if (errorReason.length() == 0) {

            // 满足执行条件 执行审核操作
            lendInventory.setItyNum(changeOrder.getCeoNeedQty());
            lendInventory.setItyWeight(changeOrder.getCeoNeedWgt());
            lendInventory.setItyAvaNum(changeOrder.getCeoNeedQty());
            lendInventory.setItyAvaWeight(changeOrder.getCeoNeedWgt());
            lendInventory.setItyPrice(needInventory.getItyPrice());
            inventoryService.addInventory(lendInventory, 1);
            inventoryService.subInventory(needInventory, changeOrder.getCeoNeedQty(), changeOrder.getCeoNeedWgt(), changeOrder.getCeoNeedQty(), changeOrder.getCeoNeedWgt());

            // 更改提报计划表状态
            if (changeOrder.getCeoRppId() != null) {
                BReportPlan reportPlan = new BReportPlan();
                reportPlan.setRppId(changeOrder.getCeoRppId());
                reportPlan.setRppIsFlag(0); // 是否选择库存标志 0=否 1=是
                reportPlanMapper.updateByPrimaryKeySelective(reportPlan);
            }

            // 更改串料申请状态（ceo_status 0删除 1保存 2提交 3执行 4已出库 5归还中 6已归还 7驳回）
            changeOrder.setCeoNeedItyId(null);
            changeOrder.setCeoStatus(2);
            changeOrder.setCeoCheckDate(null);
            changeOrder.setCeoCheckUser(null);
            changeOrder.setCeoRppId(null);
            changeOrderDao.updateByPrimaryKey(changeOrder);

        } else {
            msg = msg + errorReason + "  ，执行失败！";
            return msg;
        }

        logService.saveLog("串料申请撤销", "单据编号：" + changeOrder.getCeoCode() + "<br> 原料描述：" + changeOrder.getCeoNeedMatDesc()
                + "<br> 跟踪号：" + changeOrder.getCeoNeedTrackCode() + "<br> 项目信息" + changeOrder.getCeoNeedCode() + "  " + changeOrder.getCeoNeedDesc()
                + "<br> 重量：" + changeOrder.getCeoNeedWgt());
        return "执行成功！";
    }

    /**
     * 校验是否满足执行（审核）条件
     *
     * @param changeOrder 串料申请单
     * @param inventory   原料库存
     * @return
     */
    private String checkValidate(MChangeOrder changeOrder, MInventory inventory) {

        String errorReason = "";
        // 如果已经被执行，不允许二次执行(ceo_status 0：删除 1：已保存  2：提交 ，3：执行，4已出库 ，5：归还中，6：已归还)
        // 提示信息：申请单号 原料描述 失败原因
        if (changeOrder.getCeoStatus() != 2) {

            errorReason = errorReason + "<br>" + changeOrder.getCeoCode() + "  " + changeOrder.getCeoNeedMatDesc() + "  非提交状态";
        }

        // 如果串料申请单执行，判断可用库存是否充足
        if (inventory == null || inventory.getItyAvaNum() < changeOrder.getCeoNeedQty()
                || inventory.getItyAvaWeight() < changeOrder.getCeoNeedWgt()) {
            errorReason = errorReason + "<br>" + changeOrder.getCeoCode() + "  " + changeOrder.getCeoNeedMatDesc() + "  可用在库库存量不足";
        }
        return errorReason;
    }

    /**
     * 校验是否满足撤销条件
     *
     * @param changeOrder 串料申请单
     * @param inventory   原料库存
     * @return
     */
    private String checkCancelValidate(MChangeOrder changeOrder, MInventory inventory) {

        String errorReason = "";
        // 如果已经被撤销，不允许二次撤销(ceo_status 0：删除 1：已保存  2：提交 ，3：执行，4已出库 ，5：归还中，6：已归还)
        // 提示信息：申请单号 原料描述 失败原因
        if (changeOrder.getCeoStatus() != 3) {

            errorReason = errorReason + "<br>" + changeOrder.getCeoCode() + "  " + changeOrder.getCeoNeedMatDesc() + "  非执行状态";
        }

        // 如果串料申请单执行，判断可用库存是否充足
        if (inventory == null || inventory.getItyAvaNum() < changeOrder.getCeoNeedQty()
                || inventory.getItyAvaWeight() < changeOrder.getCeoNeedWgt()) {
            errorReason = errorReason + "<br>" + changeOrder.getCeoCode() + "  " + changeOrder.getCeoNeedMatDesc() + "  可用在库库存量不足";
        }

        return errorReason;
    }

    /**
     * 满足执行条件 执行审核操作
     *
     * @param changeOrder 串料申请单
     * @param inventory   原料在库
     */
    private void checkChangeOrderMethod(MChangeOrder changeOrder, MInventory inventory) {

        // 拆分新的一条库存在库记录，同时减少被串用库存量
        MInventory newInVentory = new MInventory();
        newInVentory.setItyMatId(inventory.getItyMatId());
        newInVentory.setItyInType(2);   // 在库类型  1：库存在库 2：项目在库
        newInVentory.setItyProCode(changeOrder.getCeoNeedCode());
        newInVentory.setItyProName(changeOrder.getCeoNeedName());
        newInVentory.setItySpec(inventory.getItySpec());
        newInVentory.setItyTrackCode(inventory.getItyTrackCode());
        newInVentory.setItyNum(changeOrder.getCeoNeedQty());
        newInVentory.setItyWeight(changeOrder.getCeoNeedWgt());
        newInVentory.setItyAvaNum(changeOrder.getCeoNeedQty());
        newInVentory.setItyAvaWeight(changeOrder.getCeoNeedWgt());

        // 应原料科要求：返料日期 自动填写成'yyyy/MM/dd划'
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
        newInVentory.setItyBackDate(dateFormat.format(changeOrder.getCeoBillDate()) + "串");

        newInVentory.setItyPrice(inventory.getItyPrice());
        newInVentory.setItyStoId(inventory.getItyStoId());
        newInVentory.setItyMatSapCode(inventory.getItyMatSapCode());
        newInVentory.setItyCeoSourceFlag(1);
        newInVentory = inventoryService.addInventory(newInVentory, 1);

        // 减少被串用物料库存量
        inventoryService.subInventory(inventory, changeOrder.getCeoNeedQty(), changeOrder.getCeoNeedWgt(), changeOrder.getCeoNeedQty(), changeOrder.getCeoNeedWgt());

        // 更改串料申请状态（ceo_status 0删除 1保存 2提交 3执行 4已出库 5归还中 6已归还）
        changeOrder.setCeoNeedItyId(newInVentory.getItyId());
        changeOrder.setCeoStatus(3);
        changeOrder.setCeoCheckDate(new Date());
        changeOrder.setCeoCheckUser(ShiroUtils.getUser().getName());
        changeOrder.setCeoPrice(inventory.getItyPrice());
        changeOrderDao.updateByPrimaryKeySelective(changeOrder);
    }

    /**
     * 项目编码是否存在
     *
     * @param param
     * @return
     */
    public Boolean codeExist(MProCodeQueryModel param) {
        Boolean boolExist;
        List<ProjectStatusModel> projectStatusModels = orderDetailDao.findProjectByCode(param);
        if (projectStatusModels == null || projectStatusModels.size() == 0) {
            boolExist = false;
        } else {
            boolExist = true;
        }
        return boolExist;
    }


}
